pub use raw_data::*;

pub trait RawData {
	fn as_raw_data(&self) -> &[u8];
	fn as_raw_mut(&mut self) -> &mut [u8];
}

#[macro_export]
macro_rules! raw_data_def {
	($($ci:ty),*) => {
		$(
			impl crate::raw::RawData for $ci {
				fn as_raw_data(& self) -> &[u8] {
					unsafe { std::mem::transmute::<&Self,&[u8;std::mem::size_of::<Self>()]>(self) }
				}
				fn as_raw_mut(&mut self) -> &mut [u8] {
					unsafe { std::mem::transmute::<&mut Self,&mut [u8;std::mem::size_of::<Self>()]>(self) }
				}
			}
		)*
	}
}

raw_data_def!{
	u16,
	u32,
	u64,
	i16,
	i32,
	i64,
	bool,
	usize
}

pub mod raw_tests {
	use super::*;
	const TEST_LEN:usize = 0x1000;
	
	#[derive(RawData)]
	struct TestChunk {
		_len:usize,
		_cap:usize,
		_data:[u8;TEST_LEN],
	}
	
	impl TestChunk {
		pub fn new() -> Self {
			Self {
				_len:0,
				_cap:0,
				_data:[0;TEST_LEN],
			}
		}
		
		pub fn read_from(&mut self,data:&[u8]) -> usize {
			let mut len = 0;
			for (e,d) in self.as_raw_mut().iter_mut().zip(data.iter()) {
				len += 1;
				*e = *d;
			}
			len
		}
		
		pub fn write_to(&self,data:&mut [u8]) -> usize {
			let mut len = 0;
			for (e,d) in self.as_raw_data().iter().zip(data.iter_mut()) {
				len += 1;
				*d = *e;
			}
			len
		}
	}

	pub fn test() {
        	let mut test_data = [0;2*TEST_LEN];
        	let mut result_data = [0;2*TEST_LEN];
        	for (i,e) in test_data.iter_mut().enumerate() { *e = (i % 256) as u8; }
        	let mut test_chunk = TestChunk::new();
        	let len1 = test_chunk.read_from(&test_data);
        	let len2 = test_chunk.write_to(&mut result_data);
        	assert_eq!(len1,len2);
        	for i in 0..len1 {
        		println!("{} {}",test_data[i],result_data[i]);
        		assert_eq!(test_data[i],result_data[i]);
        	}
	}
}
